package com.et114.core.utility;


//@author guanhw
public class StringUtils {
	private static char hexDigits[] = {
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		'A', 'B', 'C', 'D', 'E', 'F'
	};

	
	public final boolean isEmpty( String s ) {
		return ( s == null || "".equals ( s.trim ( ) ) ) ;
	}
	
	public final static boolean isSpaceString(String s) {
		if (s == null) {
			return true;
		}
		for (int i = 0, len = s.length(); i < len; i++) {
			char c = s.charAt(i);
			if (!Character.isWhitespace(c)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 将一个长整数中的指定字节数转化成16进制串
	 * @param l 长整数
	 * @param byteNum 长整数中的低字节数(即从右往左的字节个数)
	 */
	public final static String toHexString(long l, int byteNum) {
		StringBuffer sb = new StringBuffer(16);
		appendHexString(sb, l, byteNum);
		return sb.toString();
	}

	/**
	 * 将一个长整数中的指定字节数转化成16进制串，并增加到字符串缓冲区中
	 * @param sb 字符串缓冲区
	 * @param l 长整数
	 * @param byteNum 长整数中的低字节数(即从右往左的字节个数)
	 */
	public final static void appendHexString(StringBuffer sb, long l, int byteNum) {
		for (int i = byteNum * 2 - 1; i >= 0; i--) {
			long x = (l >> (i * 4)) & 0xf;
			sb.append(hexDigits[ (int) x]);
		}
	}

	/**
	 * 将字符串中unicode字符转换为&#92;uxxxx形式，并对'\\','\t','\n','\r','\f'进行
	 * 处理，还对specialChars中任何字符加前导\
	 * @params s 需要处理的字符串
	 * @params sb 追加处理结果的缓冲区
	 * @params specialChars 需要加前导\的特别字符串
	 * @return 若sb!=null则返回sb，否则返回追加了处理结果的新StringBuffer
	 */
	public final static StringBuffer deunicode(String s, StringBuffer sb, String specialChars) {
		int len = s.length();
		if (sb == null) {
			sb = new StringBuffer(len * 2);

		}
		for (int i = 0; i < len; i++) {
			char ch = s.charAt(i);
			switch (ch) {
				case '\\':
					sb.append('\\').append('\\');
					break;
				case '\t':
					sb.append('\\').append('t');
					break;
				case '\n':
					sb.append('\\').append('n');
					break;
				case '\r':
					sb.append('\\').append('r');
					break;
				case '\f':
					sb.append('\\').append('f');
					break;
				default:
					if ( (ch < 0x0020) || (ch > 0x007e)) {
						sb.append('\\').append('u');
						sb.append(hexDigits[ (ch >> 12) & 0xF]);
						sb.append(hexDigits[ (ch >> 8) & 0xF]);
						sb.append(hexDigits[ (ch >> 4) & 0xF]);
						sb.append(hexDigits[ch & 0xF]);
					}
					else {
						if (specialChars != null && specialChars.indexOf(ch) != -1) {
							sb.append('\\');
						}
						sb.append(ch);
					}
			}
		}
		return sb;
	}

	public final static StringBuffer deunicode(String s, StringBuffer sb) {
		return deunicode(s, sb, null);
	}

	public final static String deunicode(String s, String specialChars) {
		return deunicode(s, null, specialChars).toString();
	}

	public final static String deunicode(String s) {
		return deunicode(s, null, null).toString();
	}

	/**
	 * 将&#92;uxxxx转换为unicode字符，并对'\\','\t','\n','\r','\f'进行处理
	 * @params s 需要处理的字符串
	 * @params sb 追加处理结果的缓冲区
	 * @return 若sb!=null则返回sb，否则返回追加了处理结果的新StringBuffer
	 */
	public final static StringBuffer unicode(String s, StringBuffer sb) {
		int len = s.length();
		if (sb == null) {
			sb = new StringBuffer(len);

		}
		char ch;
		for (int i = 0; i < len; ) {
			ch = s.charAt(i++);
			if (ch != '\\') {
				sb.append(ch);
				continue;
			}
			ch = s.charAt(i++);
			if (ch == 'u') {
				// Read the xxxx
				int value = 0;
				for (int j = 0; j < 4; j++) {
					ch = s.charAt(i++);
					switch (ch) {
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							value = (value << 4) + ch - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							value = (value << 4) + 10 + ch - 'a';
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							value = (value << 4) + 10 + ch - 'A';
							break;
						default:
							throw new IllegalArgumentException("不合法的\\uxxxx编码");
					} // switch(ch)
				} // for(int j)
				sb.append( (char) value);
			}
			else {
				switch (ch) {
					case 't':
						ch = '\t';
						break;
					case 'r':
						ch = '\r';
						break;
					case 'n':
						ch = '\n';
						break;
					case 'f':
						ch = '\f';
						break;
				}
				sb.append(ch);
			}
		} //for(int i)
		return sb;
	}

	public final static String unicode(String s) {
		return unicode(s, null).toString();
	}

	public final static String unicode2String(String theString) {
		char aChar;
		int len = theString.length();
		StringBuffer outBuffer = new StringBuffer(len);
		for (int x = 0; x < len; ) {
			aChar = theString.charAt(x++);
			if (aChar == '\\') {
				aChar = theString.charAt(x++);
				if (aChar == 'u') {
					// Read the xxxx
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = theString.charAt(x++);
						switch (aChar) {
							case '0':
							case '1':
							case '2':
							case '3':
							case '4':
							case '5':
							case '6':
							case '7':
							case '8':
							case '9':
								value = (value << 4) + aChar - '0';
								break;
							case 'a':
							case 'b':
							case 'c':
							case 'd':
							case 'e':
							case 'f':
								value = (value << 4) + 10 + aChar - 'a';
								break;
							case 'A':
							case 'B':
							case 'C':
							case 'D':
							case 'E':
							case 'F':
								value = (value << 4) + 10 + aChar - 'A';
								break;
							default:
								throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
						}
					}
					outBuffer.append( (char) value);
				} // if(aChar)
			}
			else {
				outBuffer.append(aChar);
			}
		} //for(int x)
		return outBuffer.toString();
	}

	final static char[] c1Digit = {
		'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
	final static char[] c2Digit = {
		'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'};
	final static char[] c1Unit = {
		'拾', '佰', '仟'};
	final static char[] c2Unit = {
		'十', '百', '千'};
	final static String[] chinaUnit = {
		"万", "亿", "亿万"};

	private final static StringBuffer toRMB2(long l, char[] cDigit, char[] cUnit) {
		int unit = 0, bit = 0, d;
		boolean hasZero = false,sf=false;
		StringBuffer sb = new StringBuffer(64);
		while (l > 0) {
			if (bit == 4) {
				if (unit > 2) {
					throw new IllegalArgumentException("大写不支持大于一万万亿的数");
				}

				if(sf){
					if (hasZero || l % 10 == 0) {
						sb.append(cDigit[0]);
						hasZero = false;
					}
				}else{
					int len=sb.length();
					if(len>1){
						sb.deleteCharAt(len - 1);
					}
				}
				sb.append(chinaUnit[unit]);
				unit++;
				bit = 0;
				sf=false;
			}

			d = (int) (l % 10);
			if (d > 0) {
				sf=true;
				if (hasZero) {
					sb.append(cDigit[0]);
					hasZero = false;
				}
				if (bit != 0) {
					sb.append(cUnit[bit - 1]);
				}
				sb.append(cDigit[d]);
			}
			else {
				if(sf){//数据尾部的0忽略
					hasZero = true;
				}
			}

			bit++;
			l /= 10;
		}
		return sb.reverse();
	}

	/**
	 * 将浮点数格式成人民币大写方式
	 * @param money 浮点数
	 * @return 格式化的字符串
	 * @exception IllegalArgumentException 当money<0或money>=一万万亿时
	 */
	public final static String toRMB(double money) {
		char[] cDigit = c1Digit, cUnit = c1Unit;
		StringBuffer sb = new StringBuffer(64);
		if (money < 0) {
			sb.append("负");
			money = -money;
		}
		long yuan = (long) money; //元

		if (yuan == 0) {
			sb.append("零");
		}else{
			sb.append(toRMB2(yuan, cDigit, cUnit));
		}
		sb.append('元');

		int jaoFeng = (int) ( (money + 0.001 - (long) money) * 100) % 100;
		int jao = jaoFeng / 10;
		int feng = jaoFeng % 10;
		if (jao > 0) {
			sb.append(cDigit[jao]);
			sb.append('角');
		}
		if (feng > 0) {
			if (jao == 0) {
				sb.append('零');
			}
			sb.append(cDigit[feng]);
			sb.append('分');
		}
		else {
			sb.append('整');
		}
		return sb.toString();
	}

	public final static String toChinese(long l, boolean abbreviate, boolean uppercase) {

		String fu = "";
		if (l == 0) {
			return "零";
		}
		else if (l < 0) {
			fu = "负";
			l = -l;
		}
		char[] cDigit = uppercase ? c1Digit : c2Digit;
		char[] cUnit = uppercase ? c1Unit : c2Unit;
		if (abbreviate) {
			return fu + toRMB2(l, cDigit, cUnit).toString();
		}
		else {
			StringBuffer sb = new StringBuffer(64);
			for (; l > 0; l /= 10) {
				int digit = (int) l % 10;
				sb.append(cDigit[digit]);
			}
			sb = sb.reverse();
			return fu + sb.toString();
		} //if ( abbreviate )
	}

	private final static boolean matches(String value, int pos1, String fmt, int pos2, boolean ignoreCase) {
		if (value == null || fmt == null) {
			return false;
		}
		int len1 = value.length(), len2 = fmt.length();
		while (pos2 < len2) {
			char ch = fmt.charAt(pos2++);
			if (ch == '*') {
				if (pos1 == len1) {
					while (pos2 < len2) {
						if (fmt.charAt(pos2++) != '*') {
							return false;
						}
					}
					return true;
				}
				do {
					if (matches(value, pos1, fmt, pos2, ignoreCase)) {
						return true;
					}
				}
				while (pos1++ < len1);
				return false;
			}
			if (ch == '?') {
				if (pos1 == len1) {
					return false;
				}
			}
			else {
				if (ignoreCase) {
					if (pos1 == len1 || Character.toUpperCase(ch) != Character.toUpperCase(value.charAt(pos1))) {
						return false;
					}
				}
				else {
					if (pos1 == len1 || ch != value.charAt(pos1)) {
						return false;
					}
				}
			}
			pos1++;
		}
		return pos1 == len1;
	}

	/**
	 * 判断字符串是否具有指定的格式
	 * @param value 字符串
	 * @param fmt 格式串(*表示0个或多个字符，?表示单个字符)
	 * @param ifcase 是否大小写
	 * @return 若value或fmt为null时返回false，若不匹配时也返回false，否则返回true
	 */
	public final static boolean matches(String value, String fmt, boolean ifcase) {
		return matches(value, 0, fmt, 0, ifcase);
	}

	private final static String[] provinces = {
		null, null, null, null, null, null, null, null, null, null,
		null, "北京", "天津", "河北", "山西", "内蒙古", null, null, null, null,
		null, "辽宁", "吉林", "黑龙江", null, null, null, null, null, null,
		null, "上海", "江苏", "浙江", "安微", "福建", "江西", "山东", null, null,
		null, "河南", "湖北", "湖南", "广东", "广西", "海南", null, null, null,
		"重庆", "四川", "贵州", "云南", "西藏", null, null, null, null, null,
		null, "陕西", "甘肃", "青海", "宁夏", "新疆", null, null, null, null,
		null, "台湾", null, null, null, null, null, null, null, null,
		null, "香港", "澳门", null, null, null, null, null, null, null,
		null, "国外"};

	private final static int[] wi = {
		7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1};
	private final static char[] codes = {
		'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

	/**
	 *	根据GB11643-1999<<公民身份号码>>及GB11643-1989<<社会保障号码>>规定检查身份证号是否符合规范
	 */
	public final static boolean identify(String ident) {
		if (ident == null) {
			return false;
		}

		int len = ident.length();
		if (len != 15 && len != 18) {
			return false;
		}

		for (int i = 0; i < ( (len == 15) ? 15 : 17); i++) {
			char ch = ident.charAt(i);
			if (ch < '0' || ch > '9') {
				return false;
			}
		}

		//检查户口所在县的行政区代码 GB/T2260
		int p = (ident.charAt(0) - '0') * 10 + (ident.charAt(1) - '0');
		if (p >= provinces.length || provinces[p] == null) {
			return false;
		}

		//检查出生年月日 GB/T7408
		int year = 0, month = 0, day = 0;
		if (len == 15) {
			year = 1900 + (ident.charAt(6) - '0') * 10 + (ident.charAt(7) - '0');
			month = (ident.charAt(8) - '0') * 10 + (ident.charAt(9) - '0');
			day = (ident.charAt(10) - '0') * 10 + (ident.charAt(11) - '0');
		}
		else {
			year = (ident.charAt(6) - '0') * 1000 + (ident.charAt(7) - '0') * 100
				+ (ident.charAt(8) - '0') * 10 + (ident.charAt(9) - '0');
			month = (ident.charAt(10) - '0') * 10 + (ident.charAt(11) - '0');
			day = (ident.charAt(12) - '0') * 10 + (ident.charAt(13) - '0');
		}
		if (month == 2) {
			if ( (year % 4 == 0) && ( (year % 100 != 0) || (year % 400 == 0))) {
				//闰年2月29日
				if (day > 29) {
					return false;
				}
			}
			else {
				if (day > 28) {
					return false;
				}
			}
		}
		else if (month == 4 || month == 6 || month == 9 || month == 11) {
			if (day > 30) {
				return false;
			}
		}
		else if (month <= 12) {
			if (day > 31) {
				return false;
			}
		}
		else {
			return false;
		}

		//检查校验码
		if (len == 18) {
			int[] w = wi;
			int mod = 0;
			for (int i = 0; i < 17; i++) {
				mod += (ident.charAt(i) - '0') * w[i];
			}
			mod = mod % 11;
			if (ident.charAt(17) != codes[mod]) {
				return false;
			}
		}
		return true;
	}

	public static String replace(String src, String findString, String replaceString) {
		if (src == null) {
			return src;
		}
		int len = src.length();
		if (len == 0) {
			return src;
		}
		if (findString == null) {
			return src;
		}
		int len1 = findString.length();
		if (len1 == 0) {
			return src;
		}
		if (replaceString == null) {
			return src;
		}

		int start = 0;
		StringBuffer sb = null;
		while (true) {
			int pos = src.indexOf(findString, start);
			if (pos >= 0) {
				if (sb == null) {
					sb = new StringBuffer(len + 100);
				}
				for (int i = start; i < pos; i++) {
					sb.append(src.charAt(i));
				}
				sb.append(replaceString);
				start = pos + len1;
			}
			else {
				if (sb != null) {
					for (int i = start; i < len; i++) {
						sb.append(src.charAt(i));
					}
				}
				break;
			}
		}
		if (sb != null) {
			return sb.toString();
		}
		return src;
	}

	public static void main(String[] args) {
		try {
			String s = "\\\t\f\r\n中国abc";
			System.out.println(s);
			s = deunicode(s);
			System.out.println(s);
			s = unicode(s);
			System.out.println(s);

			System.out.println("0 = " + toChinese(0, false, true));
			System.out.println("348004023 =" + toChinese(348004023, false, false));
			System.out.println("348040023 =" + toChinese(348040023, true, true));
			System.out.println("348004023 =" + toChinese(348004023, true, true));

			System.out.println(matches("", "?", true));
			System.out.println(matches("1", "?", true));
			System.out.println(matches("", "*", true));
			System.out.println(matches("123", "*", true));
			System.out.println(matches("abc123", "*123", true));
			System.out.println(matches("abc123", "*1?3", true));
			System.out.println(matches("abc123", "*3", true));
			System.out.println(matches("abc123", "*34", true));

			System.out.println(identify("420503800131001"));

			System.out.println(replace("sdfdf\"&sb\"343sbff", "sb", "***"));

			System.out.println(toHexString(342432233, 8));
			System.out.println(toHexString(342432233, 3));

		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
